package com.lemon.cloud.author.oauth2.provider;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * @Description: AuthenticationManagerBuilder中的AuthenticationProvider是进行认证的核心
 * CustomerAuthenticationProvider 主要是为AuthenticationProvider借接口的实现类  为spring security提供密码验证器  是核心配置，
 * 这儿需要注意  系统中已经有相应的实现类，如果不配置，则系统中会默认使用org.springframework.security.authentication.dao.DaoAuthenticationProvider这个类来进行验证，
 * DaoAuthenticationProvider这个类继承了org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider这个抽象类，
 * 所以我们要自定义provider验证流程可以实现AuthenticationProvider接口或者继承AbstractUserDetailsAuthenticationProvider抽象类均可
 * @author: zhoum
 * @Date: 2018-11-23
 * @Time: 9:11
 */
@Slf4j
@Component
public class CustomerAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * @param
     * @return
     * @description authentication是前台拿过来的用户名、密码bean  主要验证流程代码  注意这儿懒得用加密验证！！！
     * @author lemon
     * @date 2019-08-17 22:50
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        log.info("用户输入的用户名是：" + authentication.getName());
        log.info("用户输入的密码是：" + authentication.getCredentials());
        // 根据用户输入的用户名获取该用户名已经在服务器上存在的用户详情，如果没有则返回null
        UserDetails userDetails = userDetailsService.loadUserByUsername(authentication.getName());

        if (userDetails == null) {
            return null;
        }

        try {
            log.info("服务器上已经保存的用户名是：" + userDetails.getUsername());
            log.info("服务器上保存的该用户名对应的密码是： " + userDetails.getPassword());
            log.info("服务器上保存的该用户对应的权限是：" + userDetails.getAuthorities());

            if (authentication.getCredentials().equals(userDetails.getPassword())) {
                // 验证成功  将返回一个UsernamePasswordAuthenticaionToken对象
                log.info("LOGIN SUCCESS !!!!!!!!!!!!!!!!!!!");
                // 分别返回用户实体   输入的密码   以及用户的权限
                return new UsernamePasswordAuthenticationToken(userDetails, authentication.getCredentials(), userDetails.getAuthorities());
            }
        } catch (Exception e) {
            log.error("author failed, -------------------the error message is:-------- " + e);
            throw e;
        }

        // 如果验证不同过则返回null或者抛出异常
        return null;
    }

    /**
     *
     **/
    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}